/*
 * Shell.java
 *
 * Created on April 17, 2007, 11:17 PM
 *
 * To change this template, choose Tools | Template Manager
 * and open the template in the editor.
 */

package org.xeerkat.restlet.xmpp;

import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.StringReader;
import java.util.UUID;
import org.infoset.xml.Document;
import org.infoset.xml.DocumentLoader;
import org.infoset.xml.sax.SAXDocumentLoader;
import org.infoset.xml.util.XMLWriter;
import org.restlet.Application;
import org.restlet.Client;
import org.restlet.Component;
import org.restlet.Request;
import org.restlet.Response;
import org.restlet.Restlet;
import org.restlet.data.Form;
import org.restlet.data.MediaType;
import org.restlet.data.Metadata;
import org.restlet.data.Method;
import org.restlet.data.Parameter;
import org.restlet.data.Reference;
import org.restlet.data.Status;
import org.restlet.representation.FileRepresentation;
import org.restlet.representation.Representation;
import org.restlet.representation.StringRepresentation;
import org.restlet.routing.VirtualHost;
import org.xeerkat.xmpp.ClientConnection;
import org.xeerkat.xmpp.ID;

/**
 *
 * @author alex
 */
public class Shell extends Component
{
   
   XMPP.Identity identity;
   /** Creates a new instance of Shell */
   public Shell(XMPP xmpp,XMPP.Identity identity)
   {
      getLogService().setLoggerName("org.xeerkat.xmpp");
      
      this.identity = identity;
      // ------------------
      // Add the connectors
      // ------------------
      getServers().add(XMPP.XMPP_PROTOCOL, identity.getId().toString(),0).getContext().getAttributes().put(XMPP.XMPP_ATTR, xmpp);
      getClients().add(XMPP.XEERKAT_PROTOCOL).getContext().getAttributes().put(XMPP.XMPP_ATTR, xmpp);
      getClients().add(XMPP.XEERKAT_SYNC_PROTOCOL).getContext().getAttributes().put(XMPP.XMPP_ATTR, xmpp);
      getClients().add(XMPP.XMPP_PROTOCOL).getContext().getAttributes().put(XMPP.XMPP_ATTR, xmpp);
      
      VirtualHost host = new VirtualHost(getContext());
      host.attach("/echo",new Restlet() {
         public void handle(Request request,Response response) {
            response.setStatus(Status.SUCCESS_OK);
            response.setEntity(request.getEntity());
            Form headers = (Form)request.getAttributes().get("org.restlet.http.headers");
            if (headers!=null) {
               response.getAttributes().put("org.restlet.http.headers",headers);
            }
         }
      });
      
      getHosts().add(host);
   }
   
   public static void main(String [] args)
   {
      if (args.length!=2) {
         System.err.println("Shell from-id password");
         System.exit(1);
      }
      try {
         //XMPPConnection.DEBUG_ENABLED = true;
         String sender = args[0];
         if (sender.indexOf('/')<0) {
            sender = sender + "/shell";
         }
         ID senderId = new ID(sender);
         senderId.setPassword(args[1]);
         XMPP xmpp = new XMPP();
         XMPP.Identity id = xmpp.addIdentity(senderId);
         sender = id.getId().toString();
         id.addResponseListener(new XMPP.ResponseListener() {
            public void onManagement(ID from,String authMethod,String username,String password,Document message)
            {
               System.out.println("Upgrade available:");
               System.out.println("\tfrom: "+from);
               System.out.println("\tmethod: "+authMethod);
               System.out.println("\tusername: "+username);
               System.out.println("\tpassword: "+password);
               if (message!=null) {
                  System.out.println("\tmessage: ");
                  try {
                     XMLWriter.writeDocument(message, System.out);
                  } catch (Exception ex) {
                     ex.printStackTrace();
                  }
               }
            }
            public void onOffline(ID id)
            {
               System.out.println(id+" is offline.");
            }
            public void onOnline(ID id)
            {
               System.out.println(id+" is online.");
            }
            public void onResponse(UUID id,Response response) {
               System.out.println("ID: "+id);
               System.out.println("Status: "+response.getStatus().getCode());
               Representation rep = response.getEntity();
               if (rep!=null) {
                  System.out.println("Content-Type: "+rep.getMediaType());
                  try {
                     System.out.println(rep.getText());
                  } catch (IOException ex) {
                     ex.printStackTrace();
                  }
               } else {
                  System.out.println("(No content)");
               }
            }
         });
         Shell shell = new Shell(xmpp,id);
         shell.start();
         BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
         boolean stop = false;
         System.out.println("Online!");
         do {
            try {
               String line = reader.readLine();
               if (line==null) {
                  continue;
               }
               line = line.trim();
               String [] parts = line.split(" ");
               if (parts[0].equals("exit")) {
                  stop = true;
               } else if (parts[0].equals("manage")) {
                  if (parts.length==1) {
                     continue;
                  }
                  if (parts.length<5) {
                     System.err.println("The manage message requires parameters: manage {to} {method} {username} {password} {message}");
                     continue;
                  }
                  try {
                     ID to = parts.length>1 ? new ID(parts[1]) : null;
                     String method = parts.length>2 ? parts[2] : null;
                     String username = parts.length>3 ? parts[3] : null;
                     String password = parts.length>4 ? parts[4] : null;
                     Document message =null;
                     String content = null;
                     int next = 5;
                     if (parts.length>5 && parts[next].charAt(0)=='"') {
                        if (parts[next].charAt(parts[next].length()-1)=='"') {
                           content = parts[next].substring(1,parts[next].length()-1);
                        } else {
                           int start = next;
                           for (; start<parts.length; start++) {
                              //System.out.println(parts[start]);
                              if (parts[start].charAt(parts[start].length()-1)=='"') {
                                 break;
                              }
                           }
                           if (start==parts.length) {
                              System.err.println("Unclose quote: "+parts[2]);
                              continue;
                           }
                           StringBuilder builder = new StringBuilder();
                           builder.append(parts[2].substring(1));
                           for (int i=3; i<=start; i++) {
                              builder.append(' ');
                              builder.append(parts[i]);
                           }
                           content = builder.toString();
                           content = content.substring(0,content.length()-1);
                           //System.out.println(content);
                           next = start+1;

                        }
                     }
                     DocumentLoader loader = new SAXDocumentLoader();
                     if (content!=null) {
                        message = loader.load(new StringReader(content));
                     } else {
                        File f = new File(parts[next]);
                        message = loader.load(f.toURI());
                     }
                     System.out.println("Sending upgrade...");
                     id.sendManagement(to, method,username, password,message);
                  } catch (IllegalArgumentException ex) {
                     System.err.println(ex.getMessage());
                  }
               } else if (parts[0].equals("get")) {
                  Client client = new Client(XMPP.XEERKAT_PROTOCOL);
                  String uri = (parts[1].startsWith("xeerkat:") || parts[1].startsWith("sxeerkat:")) ? parts[1] : "xeerkat://"+sender+"/"+parts[1];
                  System.out.println("Get from: "+uri);
                  Request request = new Request(Method.GET,new Reference(uri));
                  Response response = client.handle(request);
                  outputResponse(response);
               } else if (parts[0].equals("post")) {
                  // test send
                  Client client = new Client(XMPP.XEERKAT_PROTOCOL);
                  String uri = (parts[1].startsWith("xeerkat:") || parts[1].startsWith("sxeerkat:")) ? parts[1] : "xeerkat://"+sender+"/"+parts[1];
                  String content = null;
                  int next = 2;
                  if (parts[2].charAt(0)=='"') {
                     if (parts[2].charAt(parts[2].length()-1)=='"') {
                        content = parts[2].substring(1,parts[2].length()-1);
                        next = 3;
                     } else if (parts.length>3) {
                        int start = 2;
                        for (; start<parts.length; start++) {
                           //System.out.println(parts[start]);
                           if (parts[start].charAt(parts[start].length()-1)=='"') {
                              break;
                           }
                        }
                        if (start==parts.length) {
                           System.err.println("Unclose quote: "+parts[2]);
                           continue;
                        }
                        StringBuilder builder = new StringBuilder();
                        builder.append(parts[2].substring(1));
                        for (int i=3; i<=start; i++) {
                           builder.append(' ');
                           builder.append(parts[i]);
                        }
                        content = builder.toString();
                        content = content.substring(0,content.length()-1);
                        //System.out.println(content);
                        next = start+1;

                     }
                  }
                  System.out.println("Sending to: "+uri);
                  Response response = null;
                  if (content!=null) {
                     Request request = new Request(Method.POST,new Reference(uri));
                     request.setEntity(new StringRepresentation(content,next<parts.length ? MediaType.valueOf(parts[next]) : MediaType.TEXT_PLAIN));
                     response = client.handle(request);
                  } else {
                     MediaType type = MediaType.APPLICATION_OCTET_STREAM;
                     File f = new File(parts[2]);
                     int lastPeriod = f.getName().lastIndexOf('.');
                     if (lastPeriod>=0) {
                        String ext = f.getName().substring(lastPeriod+1);
                        Application app = new Application() {
                           public Restlet createRoot() { return null; }
                        };
                        Metadata metadata = app.getMetadataService().getMetadata(ext);
                        if (metadata!=null) {
                           type = MediaType.valueOf(metadata.getName());
                        }
                     }
                     Request request = new Request(Method.POST,new Reference(uri));
                     request.setEntity(new FileRepresentation(f,type,0));
                     response = client.handle(request);
                  }
                  outputResponse(response);
               } else {
                  System.err.println("Do not understand: "+line);
               }
            } catch (Exception ex) {
               ex.printStackTrace();
            }
         } while (!stop);
         shell.stop();
         System.out.println("Bye!");
         
         System.out.println("Active threads: "+Thread.activeCount());
         ThreadGroup group = ClientConnection.getThreadGroup();
         group.list();
         
      } catch (Exception ex) {
         ex.printStackTrace();
      }
      
   }
   
   static void outputResponse(Response response)
   {
      System.out.println("Status: "+response.getStatus().getCode());
      Form headers = (Form)response.getAttributes().get("org.restlet.http.headers");
      if (headers!=null) {
         for (Parameter header : headers) {
            System.out.println(header.getName()+"="+header.getValue());
         }
      }
      Representation rep = response.getEntity();
      if (rep!=null) {
         try {
            rep.write(System.out);
         } catch (IOException ex) {
            ex.printStackTrace();
         }
      }
   }
   
}
